package com.cgnpc.scp.purchase.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cgnpc.cud.core.domain.AjaxResult;
import com.cgnpc.cuddemo.utils.IDHelper;
import com.cgnpc.scp.common.bean.CreateFileInfo;
import com.cgnpc.scp.common.bean.MyPageResult;
import com.cgnpc.scp.common.exception.ScpException;
import com.cgnpc.scp.common.pojo.UserInfo;
import com.cgnpc.scp.common.service.AppConstantService;
import com.cgnpc.scp.common.service.ExcelCustomTemplateService;
import com.cgnpc.scp.common.utils.*;
import com.cgnpc.scp.purchase.mybatis.entity.PurchaseContract;
import com.cgnpc.scp.purchase.mybatis.entity.PurchaseContractItem;
import com.cgnpc.scp.purchase.mybatis.entity.PurchaseContractItemExampleExtend;
import com.cgnpc.scp.purchase.mybatis.entity.PurchaseProject;
import com.cgnpc.scp.purchase.mybatis.mapper.client.PurchaseContractItemMapper;
import com.cgnpc.scp.purchase.service.IPurchaseContractItemService;
import com.cgnpc.scp.purchase.service.IPurchaseContractService;
import com.cgnpc.scp.purchase.service.IPurchaseProjectService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.session.SqlSession;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class PurchaseContractItemServiceImpl implements IPurchaseContractItemService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PurchaseContractItemServiceImpl.class);

    @Autowired
    private PurchaseContractItemMapper purchaseContractItemMapper;

    @Autowired
    private SqlSession sqlSession;

    @Autowired
    private AppConstantService appConstantService;

    @Autowired
    private IPurchaseProjectService purchaseProjectService;

    @Autowired
    private IPurchaseContractService purchaseContractService;

    @Autowired
    private ExcelCustomTemplateService excelCustomTemplateService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends PurchaseContractItem> MyPageResult<T> loadByPaging(T reqEntity) {
        // begin 分页查询
        // 第几页
        int pageNum = reqEntity.getPageNum();
        // 每页的数量
        int pageSize = reqEntity.getPageSize();
        // 创建Page对象，将pageNum，pageSize参数传入，必须位于数据库查询数据的语句之前，否则不生效
        com.github.pagehelper.Page<PurchaseContractItem> queryPage = PageHelper.startPage(pageNum, pageSize);

        // 创建queryExample
        PurchaseContractItemExampleExtend queryExample = createQueryExample(reqEntity);

        purchaseContractItemMapper.selectByExampleWithCustom(queryExample);

        // pagehelper分页插件的问题，需要创建PageInfo才能获取总记录数，queryPage.getResult()和dbEntityList是一样的
        PageInfo<PurchaseContractItem> pageResult = new PageInfo<>(queryPage.getResult());

        // 创建分页结果集对象
        MyPageResult<PurchaseContractItem> myPageResult = MyPageResultUtil.createMyPageResult(pageResult);

        if (myPageResult != null) {
            this.fillProjectAndContractInfo(myPageResult.getResults());
        }
        // end 分页查询

        return (MyPageResult<T>) myPageResult;
    }

    /**
     * 创建查询Example
     *
     * @param reqEntity reqEntity
     * @param <T>       T
     * @return Example
     */
    private <T extends PurchaseContractItem> PurchaseContractItemExampleExtend createQueryExample(T reqEntity) {
        // mybatis查询方式
        PurchaseContractItemExampleExtend queryExample = new PurchaseContractItemExampleExtend();

        // 设置排序字段
        // queryExample.setOrderByClause("order_index");

        // 设置查询条件

        // 合同号
        if (!StringUtil.isNullOrSpace(reqEntity.getContractNo())) {
            // queryExampleCriteria.andContractNoLike((SqlUtil.valueJoinLikeBoth(reqEntity.getContractNo())));
            // addCriterion("contract_no like", value, "contractNo");
            queryExample.setContractNoLike((SqlUtil.valueJoinLikeBoth(reqEntity.getContractNo())));
        }

        // 合同名称
        if (!StringUtil.isNullOrSpace(reqEntity.getContractName())) {
            // queryExampleCriteria.andContractNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getContractName()));
            // addCriterion("contract_name like", value, "contractName");
            queryExample.setContractNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getContractName()));
        }

        // 物项（服务）名称
        if (!StringUtil.isNullOrSpace(reqEntity.getServiceName())) {
            // queryExampleCriteria.andServiceNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getServiceName()));
            // addCriterion("service_name like", value, "serviceName");
            queryExample.setServiceNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getServiceName()));
        }

        // 物项类型
        if (reqEntity.getItemType() != null) {
            queryExample.setItemTypeEq(reqEntity.getItemType());
        }
		// 合同物项-------------多个id
        if (ListUtil.getListSizeWith0(reqEntity.getIds()) > 0) {
            // queryExampleCriteria.andProjectNameLike(SqlUtil.valueJoinLikeBoth(reqEntity.getProjectName()));
            // addCriterion("project_name like", value, "projectName");
            queryExample.setIds(reqEntity.getIds());
        }

        return queryExample;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends PurchaseContractItem> AjaxResult saveOrUpdate(UserInfo loginUserInfo, Locale reqLocale, List<T> reqEntityList) {
        final String logInfo = "[PurchaseContractItem_saveOrUpdate_UUID_" + UUID.randomUUID() + "]";
        AjaxResult ajaxResult = null;
        final List<PurchaseContractItem> resultData = new ArrayList<>();
        String tempInfo = null;

        try {
            Date nowDate = new Date();

            // begin 获取登录用户的信息
            String loginUserInfoUserId = loginUserInfo.getUserId();
            String loginUserInfoUserName = loginUserInfo.getUserName();
            // end 获取登录用户的信息

            PurchaseProject dbPurchaseProject = null;
            PurchaseContract dbPurchaseContract = null;
            PurchaseContractItem usedEntity = null;
            int saveRows = 0;
            int updateRows = 0;

            String reqId = null;
            String reqProjectId = null;
            String reqProjectCode = null;
            String reqContractId = null;
            String reqContractNo = null;
            String reqSerialNumber = null;
            Integer reqItemType = null;
            String dbProjectId = null;
            String dbProjectCode = null;
            String dbContractId = null;
            String dbContractNo = null;
            String dbContractName = null;
            String reqCurrency = null;
            BigDecimal reqAmountMoney = null;
            BigDecimal reqHanshuidj = null;
            BigDecimal reqBuhanshuidj = null;
            String reqReason = null;
            String reqFixedassets = null;
            String reqScientificresearchproject=null;
            for (PurchaseContractItem reqEntity : reqEntityList) {
                reqId = reqEntity.getId();
                reqProjectId = reqEntity.getProjectId();
                reqProjectCode = reqEntity.getProject();
                reqContractId = reqEntity.getContractId();
                reqContractNo = reqEntity.getContractNo();
                reqSerialNumber = reqEntity.getSerialNumber();
                reqItemType = reqEntity.getItemType();
                reqCurrency = reqEntity.getCurrency();
                reqAmountMoney = reqEntity.getAmountMoney();
                reqHanshuidj = reqEntity.getHanshuidj();
                reqBuhanshuidj = reqEntity.getBuhanshuidj();

                reqReason = reqEntity.getReason();
                reqFixedassets = reqEntity.getFixedassets();
                reqScientificresearchproject=reqEntity.getScientificresearchproject();

                // begin 将变量重新设值
                dbProjectId = null;
                dbProjectCode = null;
                dbContractId = null;
                dbContractNo = null;
                dbContractName = null;
                // end 将变量重新设值

                if (reqItemType == null
                        || !(
                        reqItemType == PurchaseContractItem.ITEMTYPE_1_CONTRACT
                                || reqItemType == PurchaseContractItem.ITEMTYPE_2_NOT_CONTRACT
                )) {
                    LOGGER.error("请求的物项类型不正确");
                    throw new ScpException("请求的物项类型不正确");
                }

                LOGGER.info("{}reqId:[{}];reqProjectId:{};reqContractId:{};reqItemType:{};"
                                + "reqProjectCode:{};reqContractNo:{};"
                        , logInfo
                        , reqId, reqProjectId, reqContractId, reqItemType
                        , reqProjectCode, reqContractNo
                );

                dbPurchaseProject = purchaseProjectService.loadById(reqProjectId);
                dbPurchaseContract = purchaseContractService.loadById(reqContractId);

                String usedProjectId = reqProjectId;
                String usedContractId = reqContractId;

                if (StringUtil.isNullOrSpace(reqId)) {
                    // 保存
                    if (StringUtil.isNullOrSpace(reqSerialNumber)) {
                        LOGGER.error("{}物项序号不能为空；", logInfo);
                        throw new ScpException("物项序号不能为空");
                    }

                    if (!StringUtil.isNullOrSpace(reqProjectCode)) {
                        // 校验请求的项目编码
                        if (dbPurchaseProject != null
                                && !reqProjectCode.equals(dbPurchaseProject.getProjectCode())
                        ) {
                            // 如果传递了projectId的情况下还传递了projectCode字段，
                            // 则判断reqProjectCode, dbProjectCode是否相等，不相等则退出。
                            tempInfo = "系统存在的项目编码和请求的项目编码不相等，一个请求不能存在多个项目信息";
                            LOGGER.error("{}{}", logInfo, tempInfo);
                            throw new ScpException(tempInfo);
                        }

                        if (dbPurchaseProject == null) {
                            List<PurchaseProject> dbPurchaseProjectList = purchaseProjectService.loadByProjectCode(reqProjectCode);
                            int dbPurchaseProjectListSize = ListUtil.getListSizeWith0(dbPurchaseProjectList);

                            if (dbPurchaseProjectListSize > 1) {
                                tempInfo = "根据项目编码查询到多个项目信息，系统处理失败。";
                                LOGGER.error("{}{}", logInfo, tempInfo);
                                throw new ScpException(tempInfo);
                            } else if (dbPurchaseProjectListSize == 1) {
                                dbPurchaseProject = dbPurchaseProjectList.get(0);
                            }
                        }
                    }

                    if (!StringUtil.isNullOrSpace(reqContractNo)) {
                        // 校验请求的合同号
                        if (dbPurchaseContract != null
                                && !reqContractNo.equals(dbPurchaseContract.getContractNo())
                        ) {
                            tempInfo = "系统存在的合同号和请求的合同号不相等，一个请求中不能存在多个合同号。";
                            LOGGER.error("{}{}", logInfo, tempInfo);
                            throw new ScpException(tempInfo);
                        }

                        if (dbPurchaseContract == null) {
                            List<PurchaseContract> dbPurchaseContractList = purchaseContractService.loadByContractNo(reqContractNo);
                            int dbPurchaseContractListSize = ListUtil.getListSizeWith0(dbPurchaseContractList);

                            if (dbPurchaseContractListSize > 1) {
                                tempInfo = "根据合同号查询到多个合同信息，系统处理失败。";
                                LOGGER.error("{}{}", logInfo, tempInfo);
                                throw new ScpException(tempInfo);
                            } else if (dbPurchaseContractListSize == 1) {
                                dbPurchaseContract = dbPurchaseContractList.get(0);
                            }
                        }
                    }

                    if (dbPurchaseProject != null) {
                        usedProjectId = dbPurchaseProject.getId();
                    }

                    if (dbPurchaseContract != null) {
                        usedContractId = dbPurchaseContract.getId();
                    }

                    if (StringUtil.isNullOrSpace(usedProjectId)) {
                        LOGGER.error("{}usedProjectId is null or space;usedProjectId:{};"
                                , logInfo
                                , usedProjectId
                        );
                        throw new ScpException("项目id不能为空");
                    }

                    if (reqItemType == PurchaseContractItem.ITEMTYPE_1_CONTRACT) {
                        // 合同
                        if (StringUtil.isNullOrSpace(usedContractId)) {
                            LOGGER.error("{}usedContractId is null or space;usedContractId:{};"
                                    , logInfo
                                    , usedContractId
                            );
                            throw new ScpException("合同id不能为空");
                        }

                        if (dbPurchaseContract == null) {
                            LOGGER.error("{}dbPurchaseContract is null;", logInfo);
                            throw new ScpException("合同信息不能为空");
                        }

                        dbContractId = dbPurchaseContract.getId();
                        dbContractNo = dbPurchaseContract.getContractNo();
                        dbContractName = dbPurchaseContract.getContractName();
                    } else if (reqItemType == PurchaseContractItem.ITEMTYPE_2_NOT_CONTRACT) {
                        // 非合同
                        if (!StringUtil.isNullOrSpace(usedContractId)) {
                            LOGGER.error("{}合同id必须为空;usedContractId is not null;usedContractId:{};"
                                    , logInfo
                                    , usedContractId
                            );
                            throw new ScpException("合同id必须为空");
                        }

                        if (dbPurchaseContract != null) {
                            LOGGER.error("{}合同信息必须为空;dbPurchaseContract is null;", logInfo);
                            throw new ScpException("合同信息必须为空");
                        }
                    }

                    if (dbPurchaseProject == null) {
                        LOGGER.error("{}dbPurchaseProject is null;", logInfo);
                        throw new ScpException("项目信息不能为空");
                    }

                    dbProjectId = dbPurchaseProject.getId();
                    dbProjectCode = dbPurchaseProject.getProjectCode();

                    // begin 校验合同号，物项序号的唯一性
                    if (!StringUtil.hasNullOrSpace(dbContractNo, reqSerialNumber)) {
                        PurchaseContractItem dbPurchaseContractItem = this.loadByContractNoAndSerialNumber(dbContractNo, reqSerialNumber);

                        if (dbPurchaseContractItem != null) {
                            LOGGER.error("{}保存失败，合同号，物项序号已经存在", logInfo);
                            throw new ScpException("保存失败，合同号，物项序号已经存在");
                        }
                    }
                    // end 校验合同号，物项序号的唯一性

                    usedEntity = new PurchaseContractItem();
                    usedEntity.setId(IDHelper.uuidNew());
                    usedEntity.setProcInstId(reqEntity.getProcInstId());
                    usedEntity.setContractId(dbContractId); // 合同id
                    usedEntity.setContractNo(dbContractNo); // 合同号；值为tbl_purchase_contract.contract_no；
                    usedEntity.setContractName(dbContractName); // 合同名称；值为tbl_purchase_contract.contract_name；
                    usedEntity.setSerialNumber(reqSerialNumber);
                    usedEntity.setProjectId(dbProjectId); // 项目id
                    usedEntity.setProject(dbProjectCode); // 项目；值为tbl_purchase_project.project_code；
                    usedEntity.setServiceName(reqEntity.getServiceName());
                    usedEntity.setSpecification(reqEntity.getSpecification());
                    usedEntity.setNum(reqEntity.getNum());
                    usedEntity.setUnit(reqEntity.getUnit());
                    usedEntity.setRequiredArrivalTime(reqEntity.getRequiredArrivalTime());
                    usedEntity.setPlannedCompletionTime(reqEntity.getPlannedCompletionTime());
                    usedEntity.setCreateTime(nowDate);
                    usedEntity.setCreateUser(loginUserInfoUserId);
                    usedEntity.setCreateUserName(loginUserInfoUserName);
                    usedEntity.setLastUpdateTime(nowDate);
                    usedEntity.setLastUpdateUser(loginUserInfoUserId);
                    usedEntity.setLastUpdateUserName(loginUserInfoUserName);
                    usedEntity.setItemType(reqItemType);
                    usedEntity.setCurrency(reqCurrency);
                    usedEntity.setAmountMoney(reqAmountMoney);
                    usedEntity.setHanshuidj(reqHanshuidj);
                    usedEntity.setBuhanshuidj(reqBuhanshuidj);
                    usedEntity.setReason(reqReason);
                    usedEntity.setFixedassets(reqFixedassets);
                    usedEntity.setScientificresearchproject(reqScientificresearchproject);


                    saveRows += purchaseContractItemMapper.insert(usedEntity);

                    PurchaseContractItem dbEntityNew = purchaseContractItemMapper.selectById(usedEntity.getId());
                    resultData.add(dbEntityNew);
                } else {
                    // 修改
                    if (!StringUtil.isNullOrSpace(reqProjectId)) {
                        if (dbPurchaseProject == null) {
                            LOGGER.error("{}dbPurchaseProject is null;", logInfo);
                            throw new ScpException("项目信息不能为空");
                        }
                    }

                    if (!StringUtil.isNullOrSpace(reqContractId)) {
                        if (dbPurchaseContract == null) {
                            LOGGER.error("{}dbPurchaseContract is null;", logInfo);
                            throw new ScpException("合同信息不能为空");
                        }
                    }

                    PurchaseContractItem dbEntity = purchaseContractItemMapper.selectById(reqId);

                    if (!reqItemType.equals(dbEntity.getItemType())) {
                        LOGGER.error("{}请求的物项类型和已经保存的物项类型不匹配", logInfo);
                        throw new ScpException("请求的物项类型和已经保存的物项类型不匹配");
                    }

                    if (dbPurchaseProject != null) {
                        dbProjectId = dbPurchaseProject.getId();
                        dbProjectCode = dbPurchaseProject.getProjectCode();
                    }

                    if (dbPurchaseContract != null) {
                        dbContractId = dbPurchaseContract.getId();
                        dbContractNo = dbPurchaseContract.getContractNo();
                        dbContractName = dbPurchaseContract.getContractName();
                    }

                    // begin 校验合同号，物项序号的唯一性
                    if (!StringUtil.hasNullOrSpace(dbContractNo, reqSerialNumber)) {
                        PurchaseContractItem dbPurchaseContractItem = this.loadByContractNoAndSerialNumber(dbContractNo, reqSerialNumber);

                        if (dbPurchaseContractItem != null && !dbPurchaseContractItem.getId().equals(reqId)) {
                            LOGGER.error("{}修改失败，合同号，物项序号已经存在", logInfo);
                            throw new ScpException("修改失败，合同号，物项序号已经存在");
                        }
                    }
                    // end 校验合同号，物项序号的唯一性

                    usedEntity = new PurchaseContractItem();
                    usedEntity.setId(reqId);
                    usedEntity.setProcInstId(reqEntity.getProcInstId());
                    usedEntity.setContractId(dbContractId); // 合同id
                    usedEntity.setContractNo(dbContractNo); // 合同号；值为tbl_purchase_contract.contract_no；
                    usedEntity.setContractName(dbContractName); // 合同名称；值为tbl_purchase_contract.contract_name；
                    usedEntity.setSerialNumber(reqSerialNumber);
                    usedEntity.setProjectId(dbProjectId); // 项目id
                    usedEntity.setProject(dbProjectCode); // 项目；值为tbl_purchase_project.project_code；
                    usedEntity.setServiceName(reqEntity.getServiceName());
                    usedEntity.setSpecification(reqEntity.getSpecification());
                    usedEntity.setNum(reqEntity.getNum());
                    usedEntity.setUnit(reqEntity.getUnit());
                    usedEntity.setRequiredArrivalTime(reqEntity.getRequiredArrivalTime());
                    usedEntity.setPlannedCompletionTime(reqEntity.getPlannedCompletionTime());
                    // usedEntity.setCreateTime(nowDate);
                    // usedEntity.setCreateUser(loginUserInfoUserId);
                    // usedEntity.setCreateUserName(loginUserInfoUserName);
                    usedEntity.setLastUpdateTime(nowDate);
                    usedEntity.setLastUpdateUser(loginUserInfoUserId);
                    usedEntity.setLastUpdateUserName(loginUserInfoUserName);
                    // usedEntity.setItemType(reqItemType); // 物项类型；不更新
                    usedEntity.setCurrency(reqCurrency);
                    usedEntity.setAmountMoney(reqAmountMoney);
                    usedEntity.setHanshuidj(reqHanshuidj);
                    usedEntity.setBuhanshuidj(reqBuhanshuidj);
                    usedEntity.setReason(reqReason);
                    usedEntity.setFixedassets(reqFixedassets);
                    usedEntity.setScientificresearchproject(reqScientificresearchproject);
                    updateRows += purchaseContractItemMapper.updateById(usedEntity);

                    PurchaseContractItem dbEntityNew = purchaseContractItemMapper.selectById(usedEntity.getId());
                    resultData.add(dbEntityNew);
                }
            }

            String strResultInfo = "保存" + saveRows + "行；修改" + updateRows + "行；";

            ajaxResult = AjaxResultUtil.createSuccessMessage(strResultInfo);
            ajaxResult.put(AjaxResultUtil.KEY_DATA, resultData);
        } catch (Exception e) {
            LOGGER.error("{}saveOrUpdate.error;", logInfo, e);
            throw e;
        }

        return ajaxResult;
    }

    @Override
    public <T extends PurchaseContractItem> CreateFileInfo exportExcel(T reqEntity) throws Exception {
        final String logInfo = "[exportExcel_UUID_" + UUID.randomUUID() + "]";
        CreateFileInfo createFileInfo = null;

        try {
            // 创建queryExample
            PurchaseContractItemExampleExtend queryExample = createQueryExample(reqEntity);

            // mappedStatementNamespace为mybatis生成的mapper.xml中的命名空间
            String mappedStatementNamespace = "com.cgnpc.scp.purchase.mybatis.mapper.client.PurchaseContractItemMapper";
            // mappedStatementMethod为mybatis生成的mapper.xml中的方法
            String mappedStatementMethod = "selectByExampleWithCustom";
            // mappedStatementId为具体指向的方法
            String mappedStatementId = mappedStatementNamespace + "." + mappedStatementMethod;

            // mappedStatementParameter可以为mybatis自动生成的XxxExample实体类，例如UserExample
            Object mappedStatementParameter = queryExample;

            String exportDictGroupKey = DataDictUtil.DICT_GROUP_KEY_WITH_PURCHASECONTRACTITEM_EXPORTEXCEL;

            createFileInfo = excelCustomTemplateService.createXlsxToWebDir(
                    sqlSession
                    , mappedStatementId
                    , mappedStatementParameter
                    , exportDictGroupKey
            );
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }

        return createFileInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public <T extends PurchaseContractItem> AjaxResult importFromExcel(UserInfo loginUserInfo, Locale reqLocale, MultipartFile reqFile) throws Exception {
        final String logInfo = "[importFromExcel_UUID_" + UUID.randomUUID() + "]";
        AjaxResult ajaxResult = null;
        XSSFWorkbook workbook = null;
        InputStream reqFileInputStream = null;

        try {
            if (reqFile == null) {
                return AjaxResultUtil.createErrorMessage("文件不存在");
            }

            boolean reqFileEmpty = reqFile.isEmpty();
            String reqFileName = reqFile.getName();
            String reqFileOriginalFilename = reqFile.getOriginalFilename();

            LOGGER.info("{}reqFileEmpty:{};reqFileName:{};reqFileOriginalFilename:{};"
                    , logInfo
                    , reqFileEmpty, reqFileName, reqFileOriginalFilename
            );

            if (!reqFileOriginalFilename.toLowerCase().endsWith(".xlsx".toLowerCase(Locale.ENGLISH))) {
                LOGGER.error("{}只支持.xlsx文件。", logInfo);
                return AjaxResultUtil.createErrorMessage("只支持.xlsx文件", null);
            }

            reqFileInputStream = reqFile.getInputStream();
            workbook = new XSSFWorkbook(reqFileInputStream);
            Sheet sheet = workbook.getSheetAt(0);

            Iterator<Row> itRow = sheet.rowIterator();
            int rowIndex = 0;
            Row row = null;
            Cell cell000 = null;
            Cell cell001 = null;
            Cell cell002 = null;
            Cell cell003 = null;
            Cell cell004 = null;
            Cell cell005 = null;
            Cell cell006 = null;
            Cell cell007 = null;
            Cell cell008 = null;
            Cell cell009 = null;
            Cell cell010 = null;
            Cell cell011 = null;
            Cell cell012 = null;
            Cell cell013 = null;
            String cellValue000 = null;
            String cellValue001 = null;
            String cellValue002 = null;
            String cellValue003 = null;
            String cellValue004 = null;
            String cellValue005 = null;
            String cellValue006 = null;
            String cellValue007 = null;
            String cellValue008 = null;
            String cellValue009 = null;
            String cellValue010 = null;
            String cellValue011 = null;
            String cellValue012 = null;
            String cellValue013 = null;

            final List<T> reqEntityList = new ArrayList<>();
            T reqEntity = null;
            SimpleDateFormat sdfYyyymmddHhmmss = new SimpleDateFormat(DateUtil.KEY_YYYYMMDD_HHMMSS_INCLUDE_SPLIT_CHAR);
            SimpleDateFormat sdfYyyymmdd = new SimpleDateFormat(DateUtil.KEY_YYYYMMDD_INCLUDE_SPLIT_CHAR);

            while (itRow.hasNext()) {
                row = itRow.next();

                // 第1行为标题
                if (rowIndex++ <= 0) {
                    continue;
                }

                // 流程实例id
                // 合同号
                // 合同名称
                // 物项序号
                // 项目编码（原来的项目字段）
                // 物项（服务）名称
                // 技术规格
                // 数量
                // 单位
                // 要求到货时间
                // 计划验收完成时间
                // "物项类型；1为基础数据新增的合同物项；2为非合同审批流程新增的合同物项；"
                // 币种
                // 金额

                cell000 = row.getCell(0);
                cell001 = row.getCell(1);
                cell002 = row.getCell(2);
                cell003 = row.getCell(3);
                cell004 = row.getCell(4);
                cell005 = row.getCell(5);
                cell006 = row.getCell(6);
                cell007 = row.getCell(7);
                cell008 = row.getCell(8);
                cell009 = row.getCell(9);
                cell010 = row.getCell(10);
                cell011 = row.getCell(11);
                cell012 = row.getCell(12);
                cell013 = row.getCell(13);

                cellValue000 = ExcelUtil.getCellValue(cell000);
                cellValue001 = ExcelUtil.getCellValue(cell001);
                cellValue002 = ExcelUtil.getCellValue(cell002);
                cellValue003 = ExcelUtil.getCellValue(cell003);
                cellValue004 = ExcelUtil.getCellValue(cell004);
                cellValue005 = ExcelUtil.getCellValue(cell005);
                cellValue006 = ExcelUtil.getCellValue(cell006);
                cellValue007 = ExcelUtil.getCellValue(cell007);
                cellValue008 = ExcelUtil.getCellValue(cell008);
                cellValue009 = ExcelUtil.getCellValue(cell009);
                cellValue010 = ExcelUtil.getCellValue(cell010);
                cellValue011 = ExcelUtil.getCellValue(cell011);
                cellValue012 = ExcelUtil.getCellValue(cell012);
                cellValue013 = ExcelUtil.getCellValue(cell013);

                reqEntity = (T) new PurchaseContractItem();
                reqEntityList.add(reqEntity);
                // proc_inst_id 流程实例id
                reqEntity.setProcInstId(cellValue000);
                // contract_no 合同号
                reqEntity.setContractNo(cellValue001);
                // contract_name 合同名称
                reqEntity.setContractName(cellValue002);
                // serial_number 物项序号
                reqEntity.setSerialNumber(cellValue003);
                // project 项目编码（原来的项目字段）
                reqEntity.setProject(cellValue004);
                // service_name 物项（服务）名称
                reqEntity.setServiceName(cellValue005);
                // specification 技术规格
                reqEntity.setSpecification(cellValue006);
                // num 数量
                reqEntity.setNum(NumberUtil.parseStringToIntegerWithNull(cellValue007));
                // unit 单位
                reqEntity.setUnit(cellValue008);
                // required_arrival_time 要求到货时间
                reqEntity.setRequiredArrivalTime(DateUtil.parseToDate(sdfYyyymmddHhmmss, sdfYyyymmdd, cellValue009));
                // planned_completion_time 计划验收完成时间
                reqEntity.setPlannedCompletionTime(DateUtil.parseToDate(sdfYyyymmddHhmmss, sdfYyyymmdd, cellValue010));
                // "物项类型；1为基础数据新增的合同物项；2为非合同审批流程新增的合同物项；"
                reqEntity.setItemType(NumberUtil.parseStringToIntegerWithNull(cellValue011));
                // 币种
                reqEntity.setCurrency(cellValue012);
                // 金额
                reqEntity.setAmountMoney(NumberUtil.parseStringToBigDecimalWithNull(cellValue013));

                if (ListUtil.getListSizeWith0(reqEntityList) >= SqlUtil.INSERT_BATCH_MAX_ROWS) {
                    saveOrUpdate(loginUserInfo, reqLocale, reqEntityList);
                    reqEntityList.clear();
                }
            }

            if (ListUtil.getListSizeWith0(reqEntityList) > 0) {
                saveOrUpdate(loginUserInfo, reqLocale, reqEntityList);
                reqEntityList.clear();
            }

            ajaxResult = AjaxResultUtil.createSuccessMessage("保存成功");
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        } finally {
            IOUtil.closeStream(reqFileInputStream);
            ExcelUtil.closeWorkbook(workbook);
        }

        return ajaxResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends PurchaseContractItem> AjaxResult del(UserInfo loginUserInfo, Locale reqLocale, T reqEntity) {
        final String logInfo = "[del_UUID_" + UUID.randomUUID().toString() + "]";

        try {
            List<String> reqIds = reqEntity.getIds();

            LOGGER.info("{}printInfo;reqIds:{};"
                    , logInfo
                    , reqIds
            );

            if (ListUtil.getListSizeWith0(reqIds) <= 0) {
                return AjaxResultUtil.createSuccessMessage("请求参数不正确");
            }

            int delRows = purchaseContractItemMapper.deleteBatchIds(reqIds);
            LOGGER.info("{}delRows:{};", logInfo, delRows);

            return AjaxResultUtil.createSuccessMessage("删除成功，共删除" + delRows + "行记录。");
        } catch (Exception e) {
            LOGGER.error("{}error;", logInfo, e);
            throw e;
        }
    }

    @Override
    public <T extends PurchaseContractItem> T loadById(String id) {
        if (StringUtil.isNullOrSpace(id)) {
            return null;
        }

        PurchaseContractItem dbPurchaseContractItem = purchaseContractItemMapper.selectById(id);

        if (dbPurchaseContractItem != null) {
            fillProjectAndContractInfo(Arrays.asList(dbPurchaseContractItem));
        }

        return (T) dbPurchaseContractItem;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public <T extends PurchaseContractItem> List<T> loadByIdList(List<String> idList) {
        if (ListUtil.getListSizeWith0(idList) <= 0) {
            return null;
        }

        List<PurchaseContractItem> dbPurchaseContractItemList = purchaseContractItemMapper.selectBatchIds(idList);

        this.fillProjectAndContractInfo(dbPurchaseContractItemList);

        return (List<T>) dbPurchaseContractItemList;
    }

    @Override
    public PurchaseContractItem loadByContractNoAndSerialNumber(String contractNo, String serialNumber) {
        if (StringUtil.hasNullOrSpace(contractNo, serialNumber)) {
            return null;
        }

        QueryWrapper<PurchaseContractItem> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq("contract_no", contractNo);
        queryWrapper.eq("serial_number", serialNumber);

        List<PurchaseContractItem> dbPurchaseContractItemList = purchaseContractItemMapper.selectList(queryWrapper);

        if (ListUtil.getListSizeWith0(dbPurchaseContractItemList) == 1) {
            return dbPurchaseContractItemList.get(0);
        }

        return null;
    }

    private void fillProjectAndContractInfo(List<PurchaseContractItem> purchaseContractItemList) {
        if (ListUtil.getListSizeWith0(purchaseContractItemList) > 0) {
            Map<String, PurchaseProject> cacheProjectIdWithPurchaseProjectMap = new HashMap<>();
            Map<String, PurchaseContract> cacheContractIdWithPurchaseContractMap = new HashMap<>();
            String itemProjectId = null;
            String itemContractId = null;
            PurchaseProject dbPurchaseProject = null;
            PurchaseContract dbPurchaseContract = null;

            for (PurchaseContractItem purchaseContractItem : purchaseContractItemList) {
                itemProjectId = purchaseContractItem.getProjectId();
                itemContractId = purchaseContractItem.getContractId();

                if (cacheProjectIdWithPurchaseProjectMap.containsKey(itemProjectId)) {
                    dbPurchaseProject = cacheProjectIdWithPurchaseProjectMap.get(itemProjectId);
                } else {
                    dbPurchaseProject = purchaseProjectService.loadById(itemProjectId);
                    cacheProjectIdWithPurchaseProjectMap.put(itemProjectId, dbPurchaseProject);
                }

                if (cacheContractIdWithPurchaseContractMap.containsKey(itemContractId)) {
                    dbPurchaseContract = cacheContractIdWithPurchaseContractMap.get(itemContractId);
                } else {
                    dbPurchaseContract = purchaseContractService.loadById(itemContractId);
                    cacheContractIdWithPurchaseContractMap.put(itemContractId, dbPurchaseContract);
                }

                if (dbPurchaseProject != null) {
                    purchaseContractItem.setProjectCode(dbPurchaseProject.getProjectCode());
                    purchaseContractItem.setProjectName(dbPurchaseProject.getProjectName());
                }

                if (dbPurchaseContract != null) {
                    purchaseContractItem.setContractNo(dbPurchaseContract.getContractNo());
                    purchaseContractItem.setContractName(dbPurchaseContract.getContractName());
                }
            }
        }
    }

}
